
#include "ate.h"
#include "idefs.h"
#include "fifo.h"
#include "apt32f003_uart.h"
/* open this when make lib in future
#define INSTRUCT_CODE_CAPACITY	2^8 - 1
#define ISA_CAPACITY	INSTRUCT_CODE_CAPACITY-3

#define EX_PWR_ON	INSTRUCT_CODE_CAPACITY
#define EX_JUMPTO	INSTRUCT_CODE_CAPACITY - 1
*/

#define UART_SEND_FIFO_SIZE 64
#define UART_RECV_FIFO_SIZE 64

uint8_t send_fifo[UART_SEND_FIFO_SIZE];
uint32_t send_add_in;
uint32_t send_get_out;

uint8_t recv_fifo[UART_RECV_FIFO_SIZE];
uint32_t recv_add_in;
uint32_t recv_get_out;

void fifo_init(void)
{
	send_add_in = 0;
	send_get_out = 0;
	recv_add_in = 0;
	recv_get_out = 0;
}

int vart_send_push_byte(uint8_t data)
{
	return fifo_addin(data, &send_add_in, &send_get_out, send_fifo, UART_SEND_FIFO_SIZE);
}

int uart_send_pop_byte(uint8_t * data)
{
	return fifo_getout(data, &send_add_in, &send_get_out, send_fifo, UART_SEND_FIFO_SIZE);
}

uint32_t InSending;
void clearInSending(void)
{
	InSending = 0;
}

uint32_t uart_send_push_nbytes(uint8_t * data, uint32_t n)
{
	uint32_t retv;
    uint8_t popdat;
	
    while (n>0){
        retv = vart_send_push_byte(*data);
        if(0 == retv){
            --n;
            ++data;
        }
    }

	if (0 == InSending){
		retv = uart_send_pop_byte(&popdat);
		if (0 == retv){
			InSending = -1;
			CSP_UART_SET_DATA(UART0, popdat);
		}
	}
    return n;
}

int uart_recv_push_byte(uint8_t data)
{
	return fifo_addin(data, &recv_add_in, &recv_get_out, recv_fifo, UART_RECV_FIFO_SIZE);
}

int uart_recv_pop_byte(uint8_t * data)
{
	return fifo_getout(data, &recv_add_in, &recv_get_out, recv_fifo, UART_RECV_FIFO_SIZE);
}

INST_T * ipbase = NULL;
uint32_t real_space_dimen;

AT_FRAME_T at_meta_list[50];
uint32_t meta_locator;

void * at_decode[AT_INST_ALL];
AT_MSG_CALLBACK at_msg_cb[AT_INST_ALL];

void (*user_unblock_loop)(uint32_t ctx)=NULL;

void reg_loop_func(void (*func)(uint32_t ctx))
{
	if (func)
	{
		user_unblock_loop = func;
	}
}

void reg_new_at(uint8_t inst, AT_MSG_CALLBACK atmcb)
{
	at_decode[inst] = &at_meta_list[meta_locator];
	at_msg_cb[inst] = atmcb;
}

/********************************************************************************
 * 	func:					reg_at_meta
 * 	note:  compose at meta data, 64bit (double 32bit) is a meta data
 * 
 * 	fore 32bit like this: 
 * 		High < ------- > Low
 * 	31 ~ 24 bit(msize) 		23 ~ 16 bit(msgid)		15 ~ 0 bit(ssize)
 * 	meta data length		message id				string length
 * 
 * follow 32bit as :
 * 	31 ~ 0 bit(pstr)
 * 	string pointer
 */
void reg_at_meta(uint8_t msgid, uint8_t msize, uint16_t ssize, const uint8_t * pstr)
{
	at_meta_list[meta_locator].seg_inf = (msgid ? 0 : ((uint32_t)msize << 24)) | ((uint32_t)msgid << 16) | (uint32_t)ssize;
	at_meta_list[meta_locator].seg_str = pstr;
	++meta_locator;
}

int init_ate(INST_T * pc, uint32_t dimen, void (*regisat)(void))
{
	ipbase = pc;
	real_space_dimen = dimen;
	meta_locator = 0;
	
	if (regisat){
		regisat();
		return 0;
	}
	return -1;
}


void ate_loop()
{
	uint32_t context=1;
	uint32_t ip = 0;
	INST_T itemp;
	uint32_t icode;
	uint32_t * atsp;
	uint8_t attype;
	uint32_t sendcnt;
	uint8_t * atss;
	
	fifo_init();
	clearInSending();
	
	for(;;)
	{
		itemp = ipbase[ip];
		icode = itemp.inst & 0x0FF;
		
		atsp = at_decode[icode];
		sendcnt = *atsp;
		//attype = sendcnt >> 28;
		sendcnt &= 0x000000FF;
		++atsp;
		atss = *atsp;
		uart_send_push_nbytes(atss, sendcnt);
		
		delay_nms(20000);
		if (++ip == real_space_dimen){
			ip = 0;
		}
		if (real_space_dimen > INSTRUCT_CODE_CAPACITY)
		{
			real_space_dimen = INSTRUCT_CODE_CAPACITY;
		}
		
		if (user_unblock_loop){
			user_unblock_loop(context);
		}
	}
}








